Tutorial

Tutorial 3 - Foolproofing Your API Client Library

5 steps

NOTE: Getting rewards from this quest is over as it was only applicable on the Earn app when it was part of a campaign. Therefore, submissions are not reviewed or are disabled. However, you are highly encouraged to still complete the quest to practice your understanding.

When building an API Client Library, it's crucial to ensure it's foolproof. This means making it robust, easy to use, and error-resistant, ensuring that developers, even those less experienced, can use it effectively without encountering pitfalls.

One of the effective ways to make sure our API library is working correctly is including tests for our API library code!

We also experienced that not all data that we receive from the API is consistent with its types. Thus, this makes our early API library functions to work incorrectly.

To ensure that we are doing this the right way, we will follow basic steps from learning why software testing is important, and how to interpret error messages.

We will also let you experience what it’s like when you actually miss some parts of third-party documentation which is exactly what we need you to do for this module’s challenge! 👀

⚠️ Also, be aware that there is a challenge added to this quest. The challenge is part of the quest requirements. Be sure to follow carefully! (Now that this quest is converted to a tutorial, take your time to solve and finish the challenge requirements).

🔔 For more information, you may refer to this Zendesk article.

For technical help on the StackUp platform & quest-related questions, join our Discord, head to the 🆘 | quest-help-forum channel and look for the correct thread to ask your question.

Helpful prior knowledge

Finish tutorial 2 of this learning module.


Learning Outcomes

By the end of this tutorial, you will be able to:

  • Understand the importance of testing
  • Analyse error messages
  • Use serde’s Serialise and Deserialise attributes to effectively use serde on data structures

Tutorial Steps

Total steps: 5

  • Step 1: Software Testing Is Important

    The importance of software testing is crucial to developing API libraries. This is to ensure that behaviours, states, and characteristics of our libraries stay consistent and any minor changes of the API are also minor changes for the API library.

    How we design, test, code, and do testing again is shown by the diagram below.

    This simple diagram gives us an idea of how code is typically written to become usable software for other users.

  • Step 2: Adding Our Tests

    Head out to your project and create a tests directory at the root level of your project. Then create the file all_ok.rs in the tests directory with contents

    use endoflife::request::api_request_all_rust_cycles;
    use endoflife::request::api_request_single_rust_cycle;
    
    #[test]
    fn single_version_success() {
        let known_rust_vers = ["1.78", "1.77", "1.76", "1.75", "1.74"];
    
        for rust_ver in known_rust_vers {
            let _ = api_request_single_rust_cycle(rust_ver).unwrap();
        }
    }
    
    #[test]
    fn bool_or_date_eol_field() {
        let _all_cycles = api_request_all_rust_cycles().unwrap();
    }
    Rust

    Run the following command to test your new code.

    cargo test

    It should fail as shown from the screenshot below

    Now let’s proceed to the next step.

  • Step 3: Identifying Errors Manually

    Based on our error from the previous quest, we can see that there was an issue converting a field name to a specific type. We also copied the line of code from our main.rs to one of our tests in Step 2 of this quest.

    We kept the unwrap() method to force a panic which will allow us to see the error message. This small part of the error message from the unwraps are evident on both the commands cargo run and cargo test.

    thread 'main' panicked at src/main.rs:3:53:called `Result::unwrap()` on an `Err` value: Error("invalid type: string \"2024-05-02\", expected a boolean", line: 1, column: 181)
    
    stack backtrace:

    Here it says that the field eol was expecting a boolean value “true” or “false” but got a string that looks like a date.

    We can confirm this by checking our output again using cURL or Postman by using the API endpoint https://endoflife.date/api/rust.json. See the screenshots below for a reference.

    Using cURL

    Green square shows that eol is of type bool while the red squares shows that eol is of type string or date.

    Using Postman

    Green square shows that eol is of type bool while the red squares shows that eol is of type string or date.


  • Step 4: Challenge

    Of course, it would be bad to just give away the solution to our problem. We will fix our code but with one catch, you will be tasked with a challenge 😱

    Some Help

    Before we head to the challenge, let’s add more code to help you on the way. Replace all the contents of your file src/rust.rs with the code below

    use serde::{ Serialize, Deserialize };
    
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "camelCase")]
    pub struct RustSingleCycle {
        pub release_date: Option<String>,
        pub eol: DateOrBool,
        pub latest: Option<String>,
        pub latest_release_date: Option<String>,
        pub lts: bool,
    }
    
    #[derive(Debug, Deserialize, Serialize)]
    // Insert the correct serde attribute here
    pub enum DateOrBool {
        Bool(bool),
        Date(String),
    }
    Rust

    This will be the code you need to fix the test. However, running cargo test now still returns errors. Not only that, but it is also a new error 👀

    The Challenge - Add the proper serde attribute

    Our helper enum DateOrBool has variants Bool that contains a bool type and Date contains the string type. This is to allow us to “catch” values of types bool or string from our eol field. However, we need to find the correct serde attribute to do this.

    Your challenge is to find out what the proper serde attribute is to use for the enum DateOrBool. Head to the serde documentation and look for the documentation pertaining to using enums with serde.

    ℹ️ In case you have trouble accessing the site, you can use the Wayback Machine to access an older but working archived version of the website. Here is the link https://web.archive.org/web/20240421165914/https://serde.rs/enum-representations.html .       

    The requirement of this challenge is to find the correct serde attribute. Note that the code edits required is just a one line change. If you've edited it successfully; on running the cargo test command again, you should see that all your tests should pass!

    To remind you what a serde attribute looks like, see the screenshot below with the text within the green square.

  • Step 5: Let’s Ace It! Preparing Your Submission!

    Oh you really finished the challenge? 😏 Then let’s go and submit your solution!

    Now, to make sure you successfully complete this quest, there is 1 deliverable that is required - a screenshot.

    Follow all the challenge requirements before you take the screenshot.

    Your screenshot should show:

    • your full screen, including your taskbar (for Windows and Linux) / dock (for MacOS)
    • your entire test code src/rust.rs with the correct serde attribute applied on the DateOrBool enum (see red arrow from sample screenshot below)
    • your entire successful test output shown in the terminal
    Expected Output

    Refer to the image if you are unsure. If the image is too small, right click on the image and press on 'Open Image in New Tab'.

    When labelling your screenshot, make sure to follow the format provided C28_Q3_yourusername.png.

    ℹ️ In the event that your screen is not wide enough to accommodate multiple windows side by side, you may take the screenshots separately and then merge them into one image.

    You can use any editing tool for that e.g. using Powerpoint to merge them on Windows, using Preview on MacOS/OSX or using Imagemagick on Linux e.g. running the following command

    convert image23.png image18.png +append C28_Q3_yourusername.png

    Or use a web tool such as https://www.adobe.com/express/feature/image/combine.

    Note: You can retrieve your StackUp username by clicking on the burger menu at the top right-hand corner of this page. You can check out this article for a reference on how to obtain it!

    By submitting the quest, please note that our StackUp Policy prohibits the use of multiple accounts by a single user and the submission of copied work.

Have you completed this tutorial? Click below to mark as complete

Help Center Need help?

Find articles to support you through your journey or chat with our support team.

Help Center